﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
using IM.Interfaces.GUI;
using IM.Interfaces;
using System.Xml.Serialization;
using System.Threading;
using IM.DataTypes;

namespace IM.GUI.ContactList
{
    internal partial class ContactListItem : UserControl
    {
        [Serializable]
        [XmlRoot("Font")]
        public class MyFont
        {
            [XmlIgnore]
            private Font font = null;

            [XmlAttribute("fontName")]
            public String FontName
            {
                get;
                set;
            }

            [XmlAttribute("fontSize")]
            public int FontSize
            {
                get;
                set;
            }

            public bool IsBold
            {
                get;
                set;
            }

            public MyFont()
            {
                FontName = "Calibri";
                FontSize = 10;
                IsBold = false;
            }

            public MyFont(String fontName, int fontSize)
            {
                this.FontName = fontName;
                this.FontSize = fontSize;
            }

            public void ReInitFont()
            {
                this.font.Dispose();
                this.font = null;
            }

            public Font GetFont()
            {
                FontStyle style = FontStyle.Regular;

                if (IsBold)
                    style = FontStyle.Bold;

                if (font == null)
                    font = new Font(this.FontName, this.FontSize, style);

                return font;
            }
        }

        [Serializable]
        [XmlRoot("ContactListItem")]
        public class ContactListItemSettings
        {
            [XmlElement("DefaultUsernameFont")]
            public MyFont DefaultUsernameFont
            {
                get;
                set;
            }

            [XmlElement("ActiveUsernameFont")]
            public MyFont ActiveUsernameFont
            {
                get;
                set;
            }

            [XmlElement("DefaultStatusFont")]
            public MyFont DefaultStatusFont
            {
                get;
                set;
            }

            public ContactListItemSettings()
            {
                this.DefaultUsernameFont = new MyFont();
                this.ActiveUsernameFont = new MyFont() { IsBold = true };
                this.DefaultStatusFont = new MyFont() { FontSize = 8 };
            }
        }

        private bool allowHidingOfflineContacts = false;
        public bool AllowHidingOfflineContacts
        {
            get { return allowHidingOfflineContacts; }
            set
            {
                this.allowHidingOfflineContacts = value;

                if (this.user != null)
                {
                    if (value)
                    {
                        this.Visible = user.Online;
                    }
                    else this.Visible = true;

                    if (this.Parent != null)
                        this.Parent.Invalidate();

                }

            }
        }

        private User user;
        public User User
        {
            get { return user; }
            set
            {
                this.user = value;

                if (AllowHidingOfflineContacts)
                {
                    this.Visible = user.Online;
                }
                else this.Visible = true;

                if (this.Parent != null)
                    this.Parent.Invalidate();

                this.user.OnAvaibilityChange -= new Interfaces.Protocols.UserHandler(User_OnAvaibilityChange);
                this.User.OnAvaibilityChange += new Interfaces.Protocols.UserHandler(User_OnAvaibilityChange);

                this.user.OnNicknameChange -= new Interfaces.Protocols.UserHandler(user_OnNicknameChange);
                this.User.OnNicknameChange += new Interfaces.Protocols.UserHandler(user_OnNicknameChange);

                this.user.OnPhotoChange -= new Interfaces.Protocols.UserHandler(user_OnPhotoChange);
                this.user.OnPhotoChange += new Interfaces.Protocols.UserHandler(user_OnPhotoChange);
            }
        }

        void user_OnPhotoChange(User sender)
        {
            this.Invalidate();
        }

        private SynchronizationContext uiContext;

        void user_OnNicknameChange(object sender)
        {
            this.Invalidate();
        }

        public bool IsItemActive
        {
            get;
            set;
        }

        private ContactListItemSettings settings = new ContactListItemSettings();

        public ContactListItem()
        {
            InitializeComponent();

            this.DoubleClick += new EventHandler(ContactListItem_DoubleClick);
            this.IsItemActive = false;
            this.MinimumSize = new Size(40, 25);
            uiContext = WindowsFormsSynchronizationContext.Current;
        }

        void ContactListItem_DoubleClick(object sender, EventArgs e)
        {
            IM.GUI.Widgets.ExtensionCommands.ContactListActions.GetInstance().ContactActivated(this.User);
        }

        public ContactListItem(IContainer container)
            : this()
        {
            container.Add(this);
        }

        void User_OnAvaibilityChange(User sender)
        {
            uiContext.Send(new SendOrPostCallback(delegate(object state)
            {
                if (AllowHidingOfflineContacts)
                {
                    this.Visible = sender.Online;
                }
                else this.Visible = true;

                if (this.Parent != null)
                {
                    this.Parent.Invalidate();
                }

                this.Invalidate();
            }), null);
        }

        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);

            using (Graphics g = e.Graphics)
            {
                g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighSpeed;
                g.CompositingMode = System.Drawing.Drawing2D.CompositingMode.SourceOver;

                Font font = this.settings.DefaultUsernameFont.GetFont();

                if (IsItemActive)
                    font = this.settings.ActiveUsernameFont.GetFont();

                Brush avaibilityPen = Brushes.Red;

                switch (User.Avaibility)
                {
                    case User.AvaibilityEnum.Offline: avaibilityPen = Brushes.Red;
                        break;

                    case User.AvaibilityEnum.Disconected: avaibilityPen = Brushes.Red;
                        break;

                    case User.AvaibilityEnum.Disconecting: avaibilityPen = Brushes.Red;
                        break;

                    default: avaibilityPen = Brushes.Green;
                        break;
                }

                g.FillEllipse(avaibilityPen, 5, 15, 10, 10);
                g.DrawString(User.Nickname, font, Brushes.Black, new Point(19, 12));
                g.DrawString(User.Status, this.settings.DefaultStatusFont.GetFont(), Brushes.Gray, new Point(19, 27));

                if (user.Photo != null)
                    g.DrawImage(User.Photo, 162, 5, 30, 36);
            }
        }

        public void SetTheme(ContactListItemSettings settings)
        {
            this.settings = settings;
        }

        private void ContactListItem_MouseEnter(object sender, EventArgs e)
        {
            this.IsItemActive = true;
            Invalidate();
        }

        private void ContactListItem_MouseLeave(object sender, EventArgs e)
        {
            this.IsItemActive = false;
            Invalidate();
        }
    }
}
